package org.shoukaiseki.common.utils;


import org.apache.commons.lang3.time.DateFormatUtils;
//import org.shoukaiseki.aqoeous.convert.Base62Decimal;
import org.shoukaiseki.common.exception.MessageVirtualException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Calendar;

/**
 *
 * com.hkedou.common.adsf <br>
 * @author 蒋カイセキ    Japan-Tokyo  2018-08-17 19:45:08<br>
 * ブログ http://shoukaiseki.blog.163.com/<br>
 * E-メール jiang28555@Gmail.com<br>
 **/
public class UniqueIdFactory {


    long nanoTimeTemp=-1;

    long secondTimeTemp =-1;


    /**
     * 时间戳10进制表示 20180831152041198143478644590
     * 年4位,月2位,日2位,时2位,分2位,秒2位,纳秒 9位
     */
    public static final int TYPE_NUMBER=1;

    /**
     * 时间戳62进制表示,例如:WY8VIKr0GpcSU0
     * 年2位,月1位,日1位,时1位,分1位,秒1位,纳秒 6位
     */
    public static final int TYPE_BASE62=0;

    int type= UniqueIdFactory.TYPE_BASE62;

    int numSize =29;

    /**
     * 机器码/主机编号/服务编号
     * 同样的服务在多个主机,多个服务运行,如果生成的纳秒级时间搓相等,也可通过服务编号保证唯一性
     */
    String machineCode;
    /**
     * 订单前缀
     */
    String prefix;

    byte[] prefixByte;

    byte[] machineCodeByte;

    public UniqueIdFactory(String prefix, String machineCode){
        init(prefix, machineCode);
    }

    public UniqueIdFactory(String prefix, String machineCode, int type){
        this.type=type;
        init(prefix, machineCode);
    }

    private void init(String prefix,String machinecode){
        switch (type){
            case UniqueIdFactory.TYPE_BASE62:
                numSize =13;
                break;
            case UniqueIdFactory.TYPE_NUMBER:
                numSize =29;
                break;
            default:
                numSize =13;
                break;

        }

        if(StringUtils.isBlank(prefix)){
            this.prefix=null;
        }else{
            this.prefix=prefix;
            this.numSize +=prefix.length();
            prefixByte=prefix.getBytes();
        }
        if(StringUtils.isBlank(machinecode)){
            this.machineCode =null;
        }else{
            this.machineCode =machinecode;
            this.numSize +=machinecode.length();
            machineCodeByte =machinecode.getBytes();
        }

    }


    public String createNewUniqueid(){
        return createNewUniqueidNumber();
//        switch (type){
//            case UniqueIdFactory.TYPE_NUMBER:
//                return createNewUniqueidNumber();
//
//            case UniqueIdFactory.TYPE_BASE62:
//                return createNewUniqueIdFast();
//
//            default:
//                return createNewUniqueIdFast();
//        }
    }


//    /**
//     * 20180817195037666222222
//     * 年月日时分秒纳秒级
//     * @return
//     */
//    private String createNewUniqueIdFast(){
//
//        Long[] dateMillisNanoTime = dateMillisNanoTime();
//        Long millisTime = dateMillisNanoTime[0];
//        Long nanoTime = dateMillisNanoTime[1];
//
//        Calendar cal=Calendar.getInstance();
//        cal.setTimeInMillis(millisTime);
//
//        byte[] bytes=new byte[numSize];
//        int index=0;
//        if(prefixByte!=null){
//            for (int i = 0; i < prefixByte.length; i++) {
//                bytes[index++]=prefixByte[i];
//            }
//        }
//
//        byte[]  bytesTemp;
//
//        bytesTemp= Base62Decimal.convertDecimalToBase62(cal.get(Calendar.YEAR));
//        //2位年份最大可以表示到3843年
//        index=ByteIntegerUtils.insertBytes(bytes,index,bytesTemp,0,false);
//
//
//        bytesTemp=Base62Decimal.convertDecimalToBase62(cal.get(Calendar.MONTH)+1);
//        index=ByteIntegerUtils.insertBytes(bytes,index,bytesTemp,0,false);
//
//        bytesTemp=Base62Decimal.convertDecimalToBase62(cal.get(Calendar.DATE));
//        index=ByteIntegerUtils.insertBytes(bytes,index,bytesTemp,0,false);
//
//        bytesTemp=Base62Decimal.convertDecimalToBase62(cal.get(Calendar.HOUR_OF_DAY));
//        index=ByteIntegerUtils.insertBytes(bytes,index,bytesTemp,0,false);
//
//        bytesTemp=Base62Decimal.convertDecimalToBase62(cal.get(Calendar.MINUTE));
//        index=ByteIntegerUtils.insertBytes(bytes,index,bytesTemp,0,false);
//
//        bytesTemp=Base62Decimal.convertDecimalToBase62(cal.get(Calendar.SECOND));
//        index=ByteIntegerUtils.insertBytes(bytes,index,bytesTemp,0,false);
//
//
//        bytesTemp = Base62Decimal.convertDecimalToBase62(nanoTime);
//
//        //二进制码至少为6位
//        index=ByteIntegerUtils.insertBytes(bytes,index,bytesTemp,6,true);
//
//
//        index=ByteIntegerUtils.insertBytes(bytes,index, machineCodeByte,0,false);
//        return new String(bytes).trim();
//    }

    /**
     * 20180817195037666222222
     * 年月日时分秒纳秒级
     * @return
     */
    private String createNewUniqueidNumber(){

        Long[] dateMillisNanoTime = dateMillisNanoTime();
        Long millisTime = dateMillisNanoTime[0]*1000;
        Long dateNanoTime = dateMillisNanoTime[1];


        StringBuffer sb=new StringBuffer(prefix);
//        sb.append(DateFormatUtils.format(System.currentTimeMillis(),"yyMMddHHmmss"));
//        sb.append(dateNanoTime()).append(machinecode);
        String yyyyMMddHHmmss = DateFormatUtils.format(millisTime, "yyyyMMddHHmmss");
//        String year = yyyyMMddHHmmss.substring(0, 4);
//        String month = yyyyMMddHHmmss.substring(4, 6);
//        String day = yyyyMMddHHmmss.substring(6, 8);
//        String hour = yyyyMMddHHmmss.substring(8, 10);
//        String minute = yyyyMMddHHmmss.substring(10, 12);
//        String second = yyyyMMddHHmmss.substring(12);
//        System.out.println("year="+year);
//        System.out.println("month="+month);
//        System.out.println("day="+day);
//        System.out.println("hour="+hour);
//        System.out.println("minute="+minute);
//        System.out.println("second="+second);
        sb.append(yyyyMMddHHmmss);
        sb.append(dateNanoTime);
        sb.append(machineCode);
        return sb.toString().trim();
    }

    public  synchronized Long[] dateMillisNanoTime(){
        long nanoTime ;

        //毫秒,微秒,纳秒
        nanoTime = System.nanoTime() % 1000000000;

        /**
         * 秒
         */
        long secondTime = System.currentTimeMillis()/1000;

        if( secondTime< secondTimeTemp){
            throw new MessageVirtualException("订单号生成失败,请重试");
        }else if(secondTime==secondTimeTemp){
            while (secondTime==secondTimeTemp&nanoTime==nanoTimeTemp){
                nanoTime=System.nanoTime()%1000000000;
            }
        }else{
            //生成序列时间秒数大于上次生成的时间
        }

        nanoTimeTemp=nanoTime;
        secondTimeTemp = secondTime;

        return new Long[]{ secondTime,nanoTime};
    }

}

//代码演示
/**
package com.ruoyi.project.wb.config;

        import org.shoukaiseki.common.utils.UniqueIdFactory;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;

@Configuration
public class CustomerOrderUniqueIdFactory {
//    @Resource(name = CustomerOrderUniqueIdFactory.CUSTOMER_SN_UNIQUE_ID_FACTORY)
//    private UniqueIdFactory orderSnUniqueIdFactory;

    public static final String CUSTOMER_SN_UNIQUE_ID_FACTORY="customerSnUniqueIdFactory";

    //    @Value("${wb.uniqueId.coSn.prefix:SD}")
    private String orderSnPrefix="SD";

    //    @Value("${wb.uniqueId.coSn.machineCode:01}")
    private String orderSnMachineCode="01";

//    @Resource(name = CustomerOrderUniqueIdFactory.CUSTOMER_SN_UNIQUE_ID_FACTORY)
//    private UniqueIdFactory orderSnUniqueidFactory;

    @Bean("customerSnUniqueIdFactory")
    public UniqueIdFactory customerSnUniqueIdFactory(){
        return new UniqueIdFactory(orderSnPrefix,orderSnMachineCode,UniqueIdFactory.TYPE_NUMBER);
    }


}

**/